<?php

class ClassRegistry {

	protected $__objects = array();

	protected $__map = array();

	public static function &getInstance() {
		static $instance = array();
		if (!$instance) {
			$instance[0] =& new ClassRegistry();
		}
		return $instance[0];
	}
	
	public static function init($class, $type = null) {
		$_this =& ClassRegistry::getInstance();
		$id = false;
		if (!$type) {
			$type = 'models';
		}
		if (is_array($class)) {
			$objects = $class;
			if (!isset($class[0])) {
				$objects = array($class);
			}
		} else {
			$objects = array(array('class' => $class));
		}
		$count = count($objects);		
		foreach ($objects as $key => $settings) {
			if (is_array($settings)) {
				$class = strtolower($settings['class']);
 				$type = strtolower($type);               				
				if (empty($settings['alias'])) {
					$settings['alias'] = $class;
				}
				$alias = strtolower($settings['alias']);
			
				if ($object = & ClassRegistry::getObject($type.$class)) {
					return $object;
				}
				switch ($type) {
					case 'models':
				        if (!class_exists('Model')) {
					        Loader::import('pspframework.models.model');
				        }
				        if (!class_exists('AppModel')) {
					        Loader::import($type.'.app');
				        }					
						Loader::import($type.'.'.$class);						
					    $settings['name'] = $class;						
		                $classname = ucfirst($class) . 'Model';						
				        if (class_exists($classname)) {						
                            ${$class} =& new $classname($settings);								
				        }						
					break;
					case 'controllers':
				        if (!class_exists('Controller')) {
					        Loader::import('pspframework.controllers.controller');	
				        }
				        if (!class_exists('AppController')) {
					        Loader::import('controllers.app');
				        }
						Loader::import($type.'.'.$class);					
		                $classname = ucfirst($class) . 'Controller';
				        if (class_exists($classname)) {
                            ${$class} =& new $classname();	
				        }							    	
						break;					
			        default:
				        if (class_exists($class)) {
                           	${$class} =& new $class($settings);
				        }						        
			            break;						
				}				

				if (!isset(${$class})) {
					return false;
				}
				$_this->addObject($type.$class, ${$class});                
				$_this->map($type.$alias, $type.$class);

			} elseif (is_numeric($settings)) {
				return false;
			}
		}

		if ($count > 1) {
			return true;
		}
		return ${$class};
	}


	public static function addObject($key, &$object) {
		$_this =& ClassRegistry::getInstance();
		$key = strtolower($key);
		if (!isset($_this->__objects[$key])) {
			$_this->__objects[$key] =& $object;
			return true;
		}
		return false;
	}


	public static function removeObject($key) {
		$_this =& ClassRegistry::getInstance();
		$key = strtolower($key);		
		if (isset($_this->__objects[$key])) {
			unset($_this->__objects[$key]);
		}
	}


	public static function isKeySet($key) {
		$_this =& ClassRegistry::getInstance();
		$key = strtolower($key);		
		if (isset($_this->__objects[$key])) {
			return true;
		} elseif (isset($_this->__map[$key])) {
			return true;
		}
		return false;
	}


	public static function keys($type = null) {
		$_this =& ClassRegistry::getInstance();
		$objects = array_keys($_this->__objects);
		if ($type ==null) {
		    return $objects;
		}
		foreach ($objects as $key => $object) {
		    if( !(strpos($object,$type) ===0) ) {
			    unset($objects[$key]);
			}
		}
		return $objects;
	}

	public static function &getObject($key) {
		$_this =& ClassRegistry::getInstance();
		$key = strtolower($key);		
		$return = false;
		if (isset($_this->__objects[$key])) {
			$return =& $_this->__objects[$key];
		} else {
			$key = $_this->__getMap($key);
			if (isset($_this->__objects[$key])) {
				$return =& $_this->__objects[$key];
			}
		}
		return $return;
	}


	public static function map($key, $name) {
		$_this =& ClassRegistry::getInstance();
		if (!isset($_this->__map[$key])) {
			$_this->__map[$key] = $name;
		}
	}


	public static function mapKeys() {
		$_this =& ClassRegistry::getInstance();
		return array_keys($_this->__map);
	}


	public static function __getMap($key) {
		$_this =& ClassRegistry::getInstance();	
		if (isset($_this->__map[$key])) {
			return $_this->__map[$key];
		}
	}

	public static function flush() {
		$_this =& ClassRegistry::getInstance();
		$_this->__objects = array();
		$_this->__map = array();
	}
}